package tr.edu.ege.seagent.hobnobwebapp;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import tr.edu.ege.seagent.hobnobontology.instance.HobNobResultSetSolution;
import tr.edu.ege.seagent.hobnobontology.instance.HobNobSPARQLQueries;

/**
 * Servlet implementation class HobNobServlet
 */
@WebServlet("/HobNobServlet")
public class HobNobServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public HobNobServlet() {
		super();
		// TODO Auto-generated constructor stub
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		response.setContentType("text/html");
		PrintWriter out = response.getWriter();

		findAllNotification(out, request, response);
	}

	/**
	 * This function provide us to find all notification over http. It uses
	 * {@link HobNobSPARQLQueries} class and it's
	 * {@link HobNobSPARQLQueries#findAllNotificationsOverHttp()} function.
	 * 
	 * @param out
	 *            writer.
	 * @param request
	 *            HTTP request.
	 * @param response
	 *            HTTP response.
	 * @return resultSet which includes all notification resources.
	 * 
	 */
	public List<HobNobResultSetSolution> findAllNotification(PrintWriter out,
			HttpServletRequest request, HttpServletResponse response)
			throws UnsupportedEncodingException {

		// Create object of HobnobSPARQLQueries class...
		HobNobSPARQLQueries query = new HobNobSPARQLQueries();
		// Query is being executed for finding all notifications...
		List<HobNobResultSetSolution> resultSet = query
				.findAllNotificationsOverHttp();

		// construct response HTML...
		startHTML(out, request, response);
		startTable(out);
		// get notifications list...
		List<String> notificationURIList = getNotifications(resultSet);
		// write notifications and members who notice...
		for (String notificationURI : notificationURIList) {
			List<HobNobResultSetSolution> notificationResults = getNotificationResults(
					resultSet, notificationURI);
			writeResults(out, request, notificationResults);
		}

		return resultSet;
	}

	/**
	 * Constructs a table row for the given place.
	 * 
	 * @param out
	 *            writer
	 * @param request
	 *            HTTP request.
	 * @param notificationResults
	 *            list of solutions about notification.
	 * @throws UnsupportedEncodingException
	 */
	private void writeResults(PrintWriter out, HttpServletRequest request,
			List<HobNobResultSetSolution> notificationResults)
			throws UnsupportedEncodingException {
		// getting host address with local address and local port number...
		String HOST_ADDRESS = "http://" + request.getLocalAddr() + ":"
				+ request.getLocalPort();
		// get first result to write common properties...
		HobNobResultSetSolution firstResult = notificationResults.get(0);
		// write common properties...
		String notification = firstResult.getNotification().asResource()
				.getURI();
		String[] split = notification.split("_");
		out.print("<tr>");
		out.print("<td>");

		out.print("<img src='" + request.getContextPath()
				+ "/images/location.png'/> ");
		// write notifications...
		out.println("<a href=\"" + HOST_ADDRESS
				+ "/HobNobWebApp/HobNobLocation?resourceURI="
				+ URLEncoder.encode(notification, "ISO-8859-1") + "\">"
				+ split[split.length - 1] + "</a>");

		out.print("</td>");
		// write names of members who are related with notification...
		for (HobNobResultSetSolution result : notificationResults) {
			out.print("<td>");
			out.println(result.getName().asLiteral().getString() + " ");
			out.println(result.getSurname().asLiteral().getString());
			out.print("</td>");
		}

		out.print("</tr>");
		out.print("</body>");
	}

	/**
	 * Retrieves the solution list of given notification.
	 * 
	 * @param resultSet
	 *            result list of d2rq sparql endpoint query.
	 * @param notificationURI
	 *            URI of the notification which is desired to find related
	 *            solutions.
	 * @return list of solutions
	 */
	private List<HobNobResultSetSolution> getNotificationResults(
			List<HobNobResultSetSolution> resultSet, String notificationURI) {
		List<HobNobResultSetSolution> notificationResults = new ArrayList<HobNobResultSetSolution>();
		for (HobNobResultSetSolution result : resultSet) {
			if (notificationURI.equals(result.getNotification().asResource()
					.getURI())) {
				notificationResults.add(result);
			}
		}
		return notificationResults;
	}

	/**
	 * Traverses the given result set and collects notification URIs.
	 * 
	 * @param resultSet
	 *            result of the d2rq notification query.
	 * @return a list of place URIs which are not repeated.
	 */
	private List<String> getNotifications(
			List<HobNobResultSetSolution> resultSet) {
		List<String> notifications = new ArrayList<String>();
		for (HobNobResultSetSolution result : resultSet) {
			String notificationURI = result.getNotification().asResource()
					.getURI();
			if (!notifications.contains(notificationURI)) {
				notifications.add(notificationURI);
			}
		}
		return notifications;
	}

	/**
	 * Writes the headers of the HTML table.
	 * 
	 * @param out
	 *            writer.
	 */
	private void startTable(PrintWriter out) {
		out.print("<table border=\"5\">");
		out.print("<tr>");
		out.print("<th>");
		out.print("Notification");
		out.print("</th>");
		out.print("<th>");
		out.print("Member");
		out.print("</th>");
		out.print("<th>");
		out.print("Member");
		out.print("</th>");
		out.print("</tr>");
	}

	/**
	 * Starts the HTML body and puts an image to the background.
	 * 
	 * @param out
	 *            writer.
	 * @param request
	 *            HTTP request.
	 * @param response
	 *            HTTP response.
	 */
	private void startHTML(PrintWriter out, HttpServletRequest request,
			HttpServletResponse response) {
		out.print("<body background ='" + request.getContextPath()
				+ "/images/map.jpg'>");

		response.setContentType("text/html");
		out.print("<center>");
		out.print("<span style='font-size: 250%; afont-weight:bold; color:#999; margin-left:40px'>HobNob <span style='font-weight:bold'>Web Application</span></span>");
		out.print("</center>");
		out.print("<h3> Click on the link of the resource that you want to view location details.<h3> ");
		out.print("<br>");
	}
}
